<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<link rel="stylesheet" href="css/book.css" type="text/css" />
<title>amz_server - ring_queue</title>

</head>
 
<body bgcolor="#FFFFFF" text="#000000">

<h2>Table of Contents</h2>

<ul>
  <li><a name="toc_TOC0" href="#TOC0">Introduction</a></li>
  <li><a name="toc_TOC1" href="#TOC1">Interface</a>
    <ul>
      <li><a href="#TOC2">RingQueueInterface</a>
      <ul>
        <li><a href="#TOC3">virtual int Add(const char *, uint32) = 0</a>
        <li><a href="#TOC4">virtual int Remove(char *, uint32) = 0</a>
        <li><a href="#TOC5">virtual bool Flush()</a>
      </ul>
      <li><a href="#TOC6">RingQueueBlockingInterface</a>
      <ul>
        <li><a href="#TOC7">virtual void ProduceCompletely() = 0</a>
        <li><a href="#TOC8">virtual bool CheckAllProducersComplete() = 0</a>
      </ul>
    </ul>
  <li><a name="toc_TOC2" href="#TOC9">Detail</a>
    <ul>
      <li><a href="#TOC10">RingQueueSingleModelBound</a>
      <li><a href="#TOC11">RingQueueSingleModelBoundless</a>
      <li><a href="#TOC12">RingQueueMultipleModelBound</a>
      <li><a href="#TOC13">RingQueueMultipleModelBoundless</a>
    </ul>
  <li><a name="toc_TOC2" href="#TOC14">Examle and others</a>
</ul>

<h2 class="chapter"><a name="TOC0"></a>Introduction</h2>
<p>Ring queue is a group of queues using for the model - producer/consumer.These queues have same interface. So it is easy to adapt different model framework.
</p>
<h2 class="chapter"><a name="TOC1"></a>Interface</h2>
<p>
  The interface of ring queue has 2 prototypes:
</p>
<ul>
<li><h3 class="chapter"><a name="TOC2"></a>RingQueueInterface</h3>
<p>This interface uses for the non-blocking pattern. RingQueueInterface provides some public
      defines of method, include:
</p>
<ul>
  <li><h4 class="chapter"><a name="TOC3">virtual int Add(const char *, uint32) = 0</h4></li>
    <p>This method declares how to add a new data into the ring queue. The invoker should be
          the producer.
    </p>
  <li><h4 class="chapter"><a name="TOC4">virtual int Remove(char *, uint32) = 0</h4></li>
    <p>This method declares how to read a data element  from the ring queue. The invoker should
          be the consumer.
    </p>
  <li><h4 class="chapter"><a name="TOC5">virtual bool Flush()</h4></li>
    <p>This is a special method, uses for boundless queue, generally, it will do something to flush datas
          to the place that consumers can reach.
    </p>
</ul>
</p>
<li><h3 class="chapter"><a name="TOC6"></a>RingQueueBlockingInterface</h3>
<p>If your model uses blocking pattern(etc. when the queue is empty, the consumer thread
       will be blocking until any new data is writen into the queue), you'd better choose the
       interface, because it has 2 methods, include:
</p>
  <ul>
    <li><h4 class="chapter"><a name="TOC7">virtual void ProduceCompletely() = 0</h4></li>
      <p>In the blocking pattern, you can invoke this when a producer complete its producing.
            This will check the all producers is finish their producing, if they are, this method will
            broadcast this information to all the producer threads, and these producer threads will
            be woke up, and stop their working.
      </p>
    <li><h4 class="chapter"><a name="TOC8">virtual bool CheckAllProducersComplete() = 0</h4></li>
      <p>This method uses for producer to check all the producers complete their work.
      </p>
  </ul>
</ul>


<h2 class="chapter"><a name="TOC9">Detail</h2>
<p>The implements of ring queue include:</p>
<ul>
 <li>
  <h3 class="chapter"><a name="TOC10">RingQueueSingleModelBound</h3>
    <p>This is a version of "double-thread safe". That is to say, there are only 2
        threads in this producer/consumer model, the producer thread only read
        from the queue, and the consumer one only write from the queue, Because
        of using lock-free, performances a high efficiency in this model. This queue
        uses a static length buffer, so it is called RingQueueSingleModelBound.</p>
    <p>This version supports blocking/non-blocking patterns, here the blocking
        is that, when the queue is empty, the consumer thread will be blocking until
        the producer thead writes any new data into the queue.</p>
 </li>
 <li>
  <h3 class="chapter"><a name="TOC11">RingQueueSingleModelBoundless</h3>
    <p>This version is just like RingQueueSingleModelBound, the only difference is this
        queue uses 2 buffers, the one is a static length one, the other is a dynamic length.
        When the static one is full, the element will be write to the dynamic buffer. So, this
        is called RingQueueSingleModelBoundless.</p>
    <p>This version supports blocking/non-blocking patterns.</p>
 </li>
 <li>
  <h3 class="chapter"><a name="TOC12">RingQueueMultipleModelBound</h3>
    <p>This is a version of "multiple-thread safe".it supports one or more producer threads
        and one or more consumer threads. This version uses a static length buffer, so it is
        called RingQueueMultipleModelBound.</p>
    <p>This version supports blocking/non-blocking patterns.</p>
 </li>
 <li>
  <h3 class="chapter"><a name="TOC13">RingQueueMultipleModelBoundless</h3>
    <p>This version is just like RingQueueMultipleModelBound, the only difference is this
        queue uses 2 buffers, the one is a static length one, the other is a dynamic length.
        When the static one is full, the element will be write to the dynamic buffer. So, this
        is called RingQueueSingleModelBoundless.</p>
    <p>This version supports blocking/non-blocking patterns.</p>
 </li>
</ul>

<h2 class="chapter"><a name="TOC14">Examle and others</h2>
<p>
  Here gives you some examles to show how to use these above. Just read the source code
  of the test in this directory - "amz_server/src/test/". You'd better to read "google protocol buffer",
  because we uses it in the test code. 
  If you want to know the ring queue deeply, you can read the source code in the directory - 
  "amz_server/src/thread/".
</p>

<p>
  To use the "ring queue", the producer thread and the comsumer thread usually implement like this follow pseudo code:
  <code>
  <pre>
  // This is the producer thread working method.
  void Producer::Run() {
    // This loop is to write data into the ring queue.
    while(condition) {
      // Variable ring_queue_ is a object of RingQueueSingleModelBound/
      // RingQueueSingleModelBoundless/RingQueueMultipleModelBound/
      // RingQueueMultipleModelBoundless
      this->ring_queue_->Add(element, max_size);
    }
    // Here the loop is indispensable.
    while(true) {
      // Flush data to the real queue.
      if(this->ring_queue_->Flush() == true) {
        // Flush return true value means flush all the data into the queue that consumers can reach.
        // ProduceCompletely() is to tell the ring queue a producer complete.
        this->ring_queue_->ProduceCompletely();
        break;
      }
    }
    // Reach here, the thread can quit.
  }
  // This is the consumer thread working method.
  void Consumer::Run() {
    // This loop is to read data from the ring queue.
    while(true) {
      // Here return 0 means all Producers complete in blocking pattern.
      // in non-blocking pattern 0 means the queue is empty.
      if(this->ring_queue_->Remove(buffer, size) == 0) {
        // This is check all producers complete their work.
        if(this->ring_queue_->CheckAllProducersComplete() == true) {
          // all complete, complete itslef.
          break;
        }
      }
    }
    // Reach here, the thread can quit.
  }
  </pre>
  </code>
</p>

<br><br>

<p>Go back to the <a href="index.html">index page</a>.</p>

<hr>

<p>14 Oct 2011</p>
 
<p>&copy; Copyright Tony hack 2011</p>
<p>Distributed under the terms of the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version
</p>
 
</body>
</html>
